#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File    :   BOOT_ReadDataByIdentifier_0x22_test.py
@Time    :   2025/04/14 13:31:28
@Author  :   YangLiang 
@Version :   1.0
@Contact :   yangl@genvict.com
@License :   (C)Copyright 2022-2025
@Desc    :   None
'''

import pytest
import logging
import time
import allure
import sys
from pytest_assume.plugin import assume
import Set_up

sys.dont_write_bytecode = True

# 支持的DID列表 (DID, 数据长度, 描述)
supported_dids = [
    ("F1 97", Set_up.EcuName_hex),                                              # ECU名称
    ("F0 89", Set_up.EcuHardwareVersionNumber_hex),                              # 整车厂ECU硬件版本号
    # ("F1 89", Set_up.EcuSoftwareVersionNumber_hex),                             # 整车厂ECU软件版本号
    ("F1 80", Set_up.BootLoaderSoftwareVersionNumber_hex),                      # BootLoader软件版本号
    ("F0 FA", Set_up.SoftwareIdentificationCode_hex),                            # 软件识别码
    # ("F0 7F", Set_up.ECUSoftwareVersionNumberDataIdentifier_hex),                # ECU软件版本号
    ("F1 87", Set_up.VehicleFactoryDefinedPartNumber_hex),                      # 整车厂定义零件号
    ("F0 13", Set_up.VehicleFactoryDefinedSoftwarePartNumber_hex),              # 整车厂定义软件零件号
    ("F1 84", Set_up.SoftwareFingerprintInformation_hex),                       # 应用软件指纹信息
    ("F1 93", Set_up.SupplierDefinedECUHardwareVersionNumber_hex),              # 供应商定义ECU硬件版本号
    ("F1 95", Set_up.SupplierDefinedECUSoftwareVersionNumber_hex),              # 供应商定义ECU软件版本号
    ("F1 8A", Set_up.SupplierCode_hex),                                         # 供应商代码
    # ("F1 8B", Set_up.ECUProductionDate),                                     # ECU生产日期
    # ("F1 8C", Set_up.ExactTraceCode_hex),                                       # 精确追溯码
    # ("F1 90", Set_up.VINDataIdentifier_hex),                                    # 车辆识别号
    ("F0 F1", Set_up.FlashWriteAttemptCounter_hex),                              # 刷写尝试计数器
    ("F0 F3", Set_up.ProgrammingDependencyCheckSuccessCounter_hex),              # 编程依赖检查成功计数器v
    # ("F1 A9", Set_up.ElectricalControlUnitConfigurationFileNumber_hex),          # 电控单元配置文件号
    # ("78 00", Set_up.APP_internal_version_hex),                                  # 应用程序内部版本号
    # ("78 01", Set_up.BOOT_internal_version_hex),                                 # 引导程序内部版本号
]

ReadDataByIdentifier_NRC13 = [
    ("22", "缺少DID"),
    ("22 F0", "少一个字节"),
    ("22 F1 80 01", "多一个字节"),
    ("22 F1 80 01 02 00", "多三个字节"),
    ("22 F1 80 F1 89 01", "读取两个DID多一个字节"),
    ("22 88 88 02 00 01", "读取两个错误的DID")
]

# 不支持的DID列表
ReadDataByIdentifier_NRC31 = [
    ("F0 90", "备份软件版本号"),
    ("F0 32", "标定版本号"),
    ("F0 A0", "备区Bootloader版本号"),
    ("F0 31", "标定零件号"),
    ("F0 F4", "子部件当前运行分区信息"),
    ("FD 32", "华为电子标签"),
    ("F1 5C", "密钥灌装状态"),
    ("F0 38", "无效"),
    ("F0 39", "无效"),
    ("F0 40", "无效"),
    ("F0 FF", "无效"),
    ("F1 A9", "无效"),

    # 0717修改
    ("F1 89", "boot不支持"),
    ("F0 7F", "boot不支持"),
    ("F1 8B", "boot不支持"),
    ("F1 8C", "boot不支持"),
    ("F1 90", "boot不支持"),
    ("F1 A9", "boot不支持"),
]

# 测试用例类
class Test_BOOT_ReadDataByIdentifier_Phy(object):

    def read_DID(Self, Driver, did, resp, session, iStep):
        """读取DID并验证"""
        iStep = 1
        
        if did == 'F1 84':
            iStep, uds_resp, size = Driver['CAN'].checkReqResp(Driver, '2E F1 84' + Set_up.SoftwareFingerprintInformation_hex, '6E F1 84', 2, iStep, True)
            iStep = Driver['CAN'].restartETC_Power(Driver, iStep) 
        if did == 'F1 90':
            iStep, uds_resp, size = Driver['CAN'].checkReqResp(Driver, '2E F1 90' + Set_up.VINDataIdentifier_hex, '6E F1 90', 3, iStep, True)    
        if did == 'F1 A9':
            iStep, uds_resp, size = Driver['CAN'].checkReqResp(Driver, '2E F1 A9' + Set_up.ElectricalControlUnitConfigurationFileNumber_hex, '6E F1 A9', 3, iStep, True)
        req = f"22 {did}"
        resp = f"62 {did}" + resp
        # 发送22服务请求
        iStep, uds_resp, size = Driver['CAN'].checkReqResp(Driver, req, resp, session, iStep, False)

        if did == 'F1 90':
            iStep, uds_resp, size = Driver['CAN'].checkReqResp(Driver, '2E F1 90' + '00' * 17, '6E F1 90', 3, iStep, True)    
        if did == 'F1 A9':
            iStep, uds_resp, size = Driver['CAN'].checkReqResp(Driver, '2E F1 A9' + 'FF' * 5, '6E F1 A9', 3, iStep, True)



    @allure.severity('normal')
    @allure.title('物理寻址-编程会话-读取DID正响应')
    @allure.description('测试物理寻址编程会话下读取DID的正响应')
    @pytest.mark.parametrize("req, resp", supported_dids, ids=[f"Request {did[0]}" for did in supported_dids])
    def test_ReadDataByIdentifier_Programming_phy(self, action, Driver, req, resp):
        """测试读取支持的DID"""
        iStep = 1
        if req == 'F0 F1':
            resp = '62 F0 F1'
        self.read_DID(Driver, req, resp, 2, iStep)


    @allure.severity('normal')
    @allure.title('物理寻址-编程会话-读取DID负响应NRC13')
    @allure.description('测试物理寻址编程会话下读取长度不对的DID应返回NRC13')
    @pytest.mark.parametrize("req,desc", ReadDataByIdentifier_NRC13, ids=[f"Request {req}" for req,desc in ReadDataByIdentifier_NRC13])
    def test_ReadDataByIdentifier_NRC13_Programming_phy(self, action, Driver, req, desc):
        iStep = 1
        # 发送22服务请求
        iStep, uds_resp, size = Driver['CAN'].checkReqResp(Driver, req, "7F 22 13", 2, iStep, False)

        

    @allure.severity('normal')
    @allure.title('物理寻址-编程会话-读取DID负响应NRC31')
    @allure.description('测试物理寻址编程会话下读取不支持的DID应返回NRC31')
    @pytest.mark.parametrize("did,desc", ReadDataByIdentifier_NRC31, ids=[f"Request {did}" for did,desc in ReadDataByIdentifier_NRC31])
    def test_ReadDataByIdentifier_NRC31_Programming_phy(self, action, Driver, did, desc):
        """测试读取不支持的DID应返回NRC31"""
        iStep = 1
        # 发送22服务请求
        iStep, uds_resp, size = Driver['CAN'].checkReqResp(Driver, f"22 {did}", "7F 22 31", 2, iStep, False)


    # @allure.severity('normal')
    # @allure.title('物理寻址-编程会话-未安全解锁读取DID负响应NRC33')
    # @allure.description('测试物理寻址编程会话下未安全解锁读取DID应返回NRC33')
    # @pytest.mark.parametrize("did,resp,length", supported_dids, ids=[f"Request {did}" for did,resp,length in supported_dids])
    # def test_ReadDataByIdentifier_NRC33_Programming_phy(self, action, Driver, did, resp, length):
    #     """测试未安全解锁读取DID应返回NRC33"""
    #     iStep = 1
    #     # 发送22服务请求
    #     iStep, uds_resp, size = Driver['CAN'].checkReqResp(Driver, f"22 {did}", "7F 22 33", 2, iStep, False)


    # @allure.severity('normal')
    # @allure.title('物理寻址-编程会话-车速高于3kph读取DID负响应NRC22')
    # @allure.description('测试物理寻址编程会话下车速高于3kph读取DID负响应NRC22')
    # @pytest.mark.parametrize("did,resp,length", supported_dids, ids=[f"Request {did}" for did,resp,length in supported_dids])
    # def test_ReadDataByIdentifier_NRC22_Programming_phy(self, action, Driver, did, resp, length):
    #     """测试车速限制下的DID读取"""
    #     iStep = 1
    #     # 设置车速大于3kph
    #     iStep = Driver['CAN'].SetVehicleSpeed(Driver, iStep, 8)
    #     # 尝试读取DID应返回NRC22
    #     iStep, uds_resp, size = Driver['CAN'].checkReqResp(Driver,f"22 {did}", "7F 22 22", 2, iStep, False)
    #     # 重置车速
    #     iStep = Driver['CAN'].SetVehicleSpeed(Driver, iStep, 0)


class Test_APP_ReadDataByIdentifier_Func(object):

    def read_DID(Self, Driver, did, resp, session, iStep):
        """读取DID并验证"""
        iStep = 1
        
        if did == 'F1 84':
            iStep, uds_resp, size = Driver['CAN'].checkReqResp(Driver, '2E F1 84' + Set_up.SoftwareFingerprintInformation_hex, '6E F1 84', 2, iStep, True)
            iStep = Driver['CAN'].restartETC_Power(Driver, iStep) 
        if did == 'F1 90':
            iStep, uds_resp, size = Driver['CAN'].checkReqResp(Driver, '2E F1 90' + Set_up.VINDataIdentifier_hex, '6E F1 90', 3, iStep, True)    
        if did == 'F1 A9':
            iStep, uds_resp, size = Driver['CAN'].checkReqResp(Driver, '2E F1 A9' + Set_up.ElectricalControlUnitConfigurationFileNumber_hex, '6E F1 A9', 3, iStep, True)
        req = f"22 {did}"
        resp = f"62 {did}" + resp
        # 发送22服务请求
        iStep, uds_resp, size = Driver['CAN'].checkReqResp(Driver, req, resp, session, iStep, False, 'UDSFun')

        if did == 'F1 90':
            iStep, uds_resp, size = Driver['CAN'].checkReqResp(Driver, '2E F1 90' + '00' * 17, '6E F1 90', 3, iStep, True)    
        if did == 'F1 A9':
            iStep, uds_resp, size = Driver['CAN'].checkReqResp(Driver, '2E F1 A9' + 'FF' * 5, '6E F1 A9', 3, iStep, True)



    @allure.severity('normal')
    @allure.title('物理寻址-编程会话-读取DID正响应')
    @allure.description('测试物理寻址编程会话下读取DID的正响应')
    @pytest.mark.parametrize("req, resp", supported_dids, ids=[f"Request {did[0]}" for did in supported_dids])
    def test_ReadDataByIdentifier_Programming_Func(self, action, Driver, req, resp):
        """测试读取支持的DID"""
        iStep = 1
        self.read_DID(Driver, req, resp, 2, iStep)


    @allure.severity('normal')
    @allure.title('物理寻址-编程会话-读取DID负响应NRC13')
    @allure.description('测试物理寻址编程会话下读取长度不对的DID应返回NRC13')
    @pytest.mark.parametrize("req,desc", ReadDataByIdentifier_NRC13, ids=[f"Request {req}" for req,desc in ReadDataByIdentifier_NRC13])
    def test_ReadDataByIdentifier_NRC13_Programming_Func(self, action, Driver, req, desc):
        iStep = 1
        # 发送22服务请求
        iStep, uds_resp, size = Driver['CAN'].checkReqResp(Driver, req, "7F 22 13", 2, iStep, False, 'UDSFun')


    @allure.severity('normal')
    @allure.title('功能寻址-编程会话-读取DID负响应NRC31')
    @allure.description('测试功能寻址编程会话下读取不支持的DID应返回NRC31')
    @pytest.mark.parametrize("did,desc", ReadDataByIdentifier_NRC31, ids=[f"Request {did}" for did,desc in ReadDataByIdentifier_NRC31])
    def test_ReadDataByIdentifier_NRC31_Programming_Func(self, action, Driver, did, desc):
        """测试读取不支持的DID应返回NRC31"""
        iStep = 1
        # 发送22服务请求
        iStep, uds_resp, size = Driver['CAN'].checkReqResp(Driver, f"22 {did}", "", 2, iStep, False, 'UDSFun')


    # @allure.severity('normal')
    # @allure.title('功能寻址-编程会话-未安全解锁读取DID负响应NRC33')
    # @allure.description('测试功能寻址编程会话下未安全解锁读取DID应返回NRC33')
    # @pytest.mark.parametrize("did,resp,length", supported_dids, ids=[f"Request {did}" for did,resp,length in supported_dids])
    # def test_ReadDataByIdentifier_NRC33_Programming_Func(self, action, Driver, did, resp, length):
    #     """测试未安全解锁读取DID应返回NRC33"""
    #     iStep = 1
    #     # 发送22服务请求
    #     iStep, uds_resp, size = Driver['CAN'].checkReqResp(Driver, f"22 {did}", "7F 22 33", 2, iStep, False, 'UDSFun')



    # @allure.severity('normal')
    # @allure.title('功能寻址-编程会话-车速高于3kph读取DID负响应NRC22')
    # @allure.description('测试功能寻址编程会话下车速高于3kph读取DID负响应NRC22')
    # @pytest.mark.parametrize("did,resp,length", supported_dids, ids=[f"Request {did}" for did,resp,length in supported_dids])
    # def test_ReadDataByIdentifier_NRC22_Programming_Func(self, action, Driver, did, resp, length):
    #     """测试车速限制下的DID读取"""
    #     iStep = 1
    #     # 设置车速大于3kph
    #     iStep = Driver['CAN'].SetVehicleSpeed(Driver, iStep, 8)
    #     # 尝试读取DID应返回NRC22
    #     iStep, uds_resp, size = Driver['CAN'].checkReqResp(Driver,f"22 {did}", "7F 22 22", 2, iStep, False, 'UDSFun')
    #     # 重置车速
    #     iStep = Driver['CAN'].SetVehicleSpeed(Driver, iStep, 0)



    